/**
 * XPath Query Tool - Content Script
 * 
 * This script creates an interactive XPath query panel that appears
 * when activated from the browser extension. It allows users to:
 * - Enter and test XPath queries
 * - View results in real-time
 * - Save frequently used queries
 * - Copy results to clipboard
 */

// Create shadow host and attach shadow root to isolate extension UI
let originalBody;
const shadowHost = document.createElement('div');
document.body.appendChild(shadowHost);
const shadowRoot = shadowHost.attachShadow({ mode: 'open' });

// Inject panel HTML and CSS into shadow DOM to create the query interface
// The panel contains:
// - Query input area
// - Results display
// - Action buttons
// - Saved queries table
shadowRoot.innerHTML = `
<style>
.panel-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 10px;
  box-sizing: border-box;
  background-color: #222;
  gap: 10px;
}

.row {
  display: flex;
  width: 100%;
}

.row:first-child {
  flex: 1;
}

.query-section, .result-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin: 0 5px;
}

.query-section h3, .result-section h3 {
  margin: 0 0 5px 0;
  padding: 0;
}

textarea {
  height: 5em;
  background-color: #222;
  color: white;
  border: 1px solid #444;
  padding: 5px;
  font-family: monospace;
  resize: none;
}

textarea.editable {
  border-color: #666;
}
h3 {
  color: #ccc;
}
.button-container {
  display: flex;
  gap: 10px;
  margin-top: 5px;
}
.button-container button {
  width: 100px;
  padding: 5px;
  background-color: #444;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
}
.button-container button:hover {
  background-color: #555;
}

#saved-xpaths-container {
  flex: 1;
  margin-top: 5px;
  overflow-y: auto;
  max-height: 180px;
}

#saved-xpaths-table {
  width: 100%;
  border-collapse: collapse;
  color: white;
}

#saved-xpaths-table th, 
#saved-xpaths-table td {
  padding: 8px;
  border: 1px solid #444;
  text-align: left;
}

#saved-xpaths-table th {
  background-color: #333;
}

#saved-xpaths-table tr:nth-child(even) {
  background-color: #2a2a2a;
}

#saved-xpaths-table tr:hover {
  background-color: #3a3a3a;
}

.action-links {
  display: flex;
  gap: 10px;
}

.action-links a {
  color: #4da6ff;
  cursor: pointer;
  text-decoration: none;
}

.action-links a:hover {
  text-decoration: underline;
}
/* 原有样式保持不变 */
.radio-group {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-left: 10px;
}

.separator-input-container {
  margin-left: 10px;
}

.separator-input-container label {
  color: white;
  margin-right: 5px;
}

.separator-input-container input {
  background-color: #222;
  color: white;
  border: 1px solid #444;
  padding: 5px;
  width: 200px;
}
.radio-group label {
  color: white; /* 确保文本颜色为白色 */
  cursor: pointer;
}
.radio-group input[type="radio"] {
  margin-right: 5px;
}
</style>
<div style="display: none;">
  <div class="panel-container">
  <div class="row">
    <div class="query-section">
      <h3>QUERY</h3>
      <textarea id="xpath-query" class="editable"></textarea>
    </div>
    <div class="result-section">
      <h3>RESULT</h3>
      <textarea id="xpath-result" class="result" readonly></textarea>
    </div>
  </div>
  <div class="row">
    <div class="button-container">
      <button id="clear-xpath">Clear Xpath</button>
      <button id="copy-result">Copy Result</button>
      <button id="save-xpath">Save Xpath</button>
      <div class="radio-group">
        <label>
          <input type="radio" name="textMode" value="immediate" checked>
          Only Immediate Text
        </label>
        <label>
          <input type="radio" name="textMode" value="nested">
          All Text Nested
        </label>
      </div>
      <!-- 新增的 Separator 文本输入框 -->
      <div class="separator-input-container">
        <label>Separator</label>
        <input type="text" id="separator-input" value="" placeholder="Enter separator, \\n for new line">
      </div>
    </div>
  </div>
  <div class="row">
    <div id="saved-xpaths-container">
      <table id="saved-xpaths-table">
        <tbody></tbody>
      </table>
    </div>
  </div>
</div>
`;

const xpathPanel = shadowRoot.querySelector('div');
const queryInput = shadowRoot.getElementById('xpath-query');
const resultOutput = shadowRoot.getElementById('xpath-result');
const btnClear = shadowRoot.getElementById('clear-xpath');
const btnCopy = shadowRoot.getElementById('copy-result');
const btnSave = shadowRoot.getElementById('save-xpath');
const resultH3 = shadowRoot.querySelector('.result-section h3');
const textModeRadios = shadowRoot.querySelectorAll('input[name="textMode"]');
const separatorInput = shadowRoot.getElementById('separator-input');

// Handle messages from background script to show/hide the panel
// When panel is shown:
// - Clone original page body for XPath evaluation
// - Position panel at top of viewport
// - Focus query input
chrome.runtime.onMessage.addListener((message) => {
  if (message.action === 'TOGGLE_PANEL') {
    xpathPanel.style.display = message.visible ? 'block' : 'none';
    shadowHost.style.position = message.visible ? 'fixed' : 'static';
    shadowHost.style.top = '0';
    shadowHost.style.left = '0';
    shadowHost.style.width = '100%';
    shadowHost.style.height = '200px';
    shadowHost.style.zIndex = '9999';
    if (message.visible) {
      // As panel is added as a shadow root, we can clone the original body without cloning the shadow root
      originalBody = document.body.cloneNode(true);
      queryInput.focus();
    }
  }
});

// Handle clear xpath button click - resets query input and triggers evaluation
btnClear.addEventListener('click', () => {
  queryInput.value = '';
  queryInput.dispatchEvent(new Event('input'));
});

// Handle copy result button click - copies result text to clipboard
btnCopy.addEventListener('click', () => {
  const resultText = resultOutput.value.trim();
  if (resultText) {
    navigator.clipboard.writeText(resultText).then(() => {
      console.log('Result copied to clipboard');
    }).catch(err => {
      console.error('Failed to copy:', err);
    });
  }
});

// Handle save xpath button click - saves current query to chrome.storage
// Prompts user for a name to identify the saved query
btnSave.addEventListener('click', () => {
  const xpath = queryInput.value.trim();
  if (xpath) {
    const name = prompt('Enter a name for this XPath:');
    if (name) {
      chrome.storage.local.get({savedXpaths: []}, (result) => {
        const savedXpaths = result.savedXpaths;
        savedXpaths.push({name, xpath});
        chrome.storage.local.set({savedXpaths}, () => {
          renderSavedXpaths();
          console.log('XPath saved:', name, ' total saved:', savedXpaths.length);
        });
      });
    }
  } else {
    alert('Please enter an XPath query first');
  }
});

function performXPathEvaluation(query) {
  const textMode = shadowRoot.querySelector('input[name="textMode"]:checked').value;
  const separatorValue = shadowRoot.getElementById('separator-input').value;
  const separator = (separatorValue === '\\n') ? '\n' : separatorValue;

  let xpath = query.trim();
  let isAttributeQuery = xpath.match(/@[\w-]+$/) || xpath.match(/attribute::[\w-]+$/);
  
  let output = '';
  if (isAttributeQuery) {
    const results = document.evaluate(
      xpath,
      originalBody,
      null,
      XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
      null
    );

    for (let i = 0; i < results.snapshotLength; i++) {
      const node = results.snapshotItem(i);
      output += (node.nodeValue !== undefined ? node.nodeValue : node.textContent) + '\n';
    }
  } else {
    let text_xpath;
    if (textMode === 'immediate') {
      text_xpath = './text()';
    } else {
      text_xpath = './/text()';
    }

    const top_nodes = document.evaluate(
      xpath,
      originalBody,
      null,
      XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
      null
    );

    for (let i = 0; i < top_nodes.snapshotLength; i++) {
      const node = top_nodes.snapshotItem(i);
      const text_nodes = document.evaluate(
        text_xpath,
        node,
        null,
        XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
        null
      );
      
      let text_node_value = '';
      for (let j = 0; j < text_nodes.snapshotLength; j++) {
        const text_node = text_nodes.snapshotItem(j);
        if (text_node.nodeValue.trim().length > 0) {
          text_node_value += text_node.nodeValue + separator;
        }
      }
      output += text_node_value + '\n';

    }

  }

  resultOutput.value = output;
  const resultLines = output.split('\n').filter(line => line.trim().length > 0);
  resultH3.textContent = resultLines.length > 0 ? `RESULT (${resultLines.length})` : 'RESULT';
}

function doQueryEvaluation() {
  try {
    const query = queryInput.value.trim();
    if (!query) {
      resultOutput.value = '';
      resultH3.textContent = 'RESULT';
      return;
    }
    performXPathEvaluation(query);
  } catch (e) {
    resultOutput.value = `Error: ${e.message}`;
    resultH3.textContent = 'RESULT';
  }
}

// Evaluate XPath when query changes (debounced via input event)
// Handles both attribute and text node queries
// Automatically appends text() to queries unless already specified
// Displays results count in panel header
queryInput.addEventListener('input', () => {
  doQueryEvaluation();
});

textModeRadios.forEach(radio => {
  radio.addEventListener('change', () => {
    doQueryEvaluation();
  });
});

separatorInput.addEventListener('input', () => {
  doQueryEvaluation();
});

// Render saved xpaths in table from chrome.storage
// Each entry shows name, XPath, and action links
// Action links allow deleting or selecting saved queries
function renderSavedXpaths() {
  chrome.storage.local.get({savedXpaths: []}, (result) => {
    const tableBody = shadowRoot.querySelector('#saved-xpaths-table tbody');
    tableBody.innerHTML = '';
    
    result.savedXpaths.forEach((item, index) => {
      const row = document.createElement('tr');
      
      const nameCell = document.createElement('td');
      const nameLink = document.createElement('a');
      nameLink.textContent = item.name;
      nameLink.style.cursor = 'pointer';
      nameLink.style.color = '#4da6ff';
      nameLink.onclick = () => selectXpath(item.xpath);
      nameCell.appendChild(nameLink);
      
      const xpathCell = document.createElement('td');
      xpathCell.textContent = item.xpath;
      
      const actionsCell = document.createElement('td');
      actionsCell.className = 'action-links';
      
      const deleteLink = document.createElement('a');
      deleteLink.textContent = 'Delete';
      deleteLink.onclick = () => deleteXpath(index);
      
      // const selectLink = document.createElement('a');
      // selectLink.textContent = 'Select';
      // selectLink.onclick = () => selectXpath(item.xpath);
      
      actionsCell.appendChild(deleteLink);
      // actionsCell.appendChild(selectLink);
      
      row.appendChild(nameCell);
      row.appendChild(xpathCell);
      row.appendChild(actionsCell);
      
      tableBody.appendChild(row);
    });
  });
}

// Delete xpath from storage by index and refresh table
function deleteXpath(index) {
  chrome.storage.local.get({savedXpaths: []}, (result) => {
    const savedXpaths = result.savedXpaths;
    savedXpaths.splice(index, 1);
    chrome.storage.local.set({savedXpaths}, () => {
      renderSavedXpaths();
    });
  });
}

// Select xpath and set to query input, triggering evaluation
function selectXpath(xpath) {
  queryInput.value = xpath;
  queryInput.dispatchEvent(new Event('input'));
}

// Initialize saved queries table when panel is shown
chrome.runtime.onMessage.addListener((message) => {
  if (message.action === 'TOGGLE_PANEL' && message.visible) {
    renderSavedXpaths();
  }
});
